#include "GUI/Shell/shellguiimpl.hpp"

#include "image.h"
#include "log.h"
#include "Frame/states.hpp"

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;

ShellGUIImpl *ShellGUIImpl::_guiimpl = 0;

ShellGUIImpl::ShellGUIImpl()
{
    _guiimpl = this;
}

int ShellGUIImpl::Init(int argc, char** argv)
{
    return -1;
}

int ShellGUIImpl::MainLoop()
{
    Start();
    return -1;
}

int ShellGUIImpl::CreateWindow()
{
    namedWindow( "Main Result");
    setMouseCallback( "Main Result", onMouse, 0 );
    return -1;
}

void ShellGUIImpl::Update(const Image& image)
{
    Mat out;
    cvtColor(Mat(image.height, image.width, CV_8UC3, image.data), out, CV_BGR2RGB);
    imshow( "Main Result", out );
}

void ShellGUIImpl::DoEvents(int s)
{
    char c = (char)waitKey(s);
    if( c == 27 || c == 'q' || c== 'Q')
    {
        Stop();
        Log("Quit");
        return;
    }
    switch(c)
    {
    case 'a':
    case 'A':
        m_state->C_event = States::L_Move;
        m_state->EventChangedFlag = true;
        break;
    case 'd':
    case 'D':
        m_state->C_event = States::R_Move;
        m_state->EventChangedFlag = true;
        break;
    case 'w':
    case 'W':
        m_state->C_event = States::U_Move;
        m_state->EventChangedFlag = true;
        break;
    case 's':
    case 'S':
        m_state->C_event = States::D_Move;
        m_state->EventChangedFlag = true;
        break;
    case 'l':
    case 'L':
        m_state->C_event = States::L_Size;
        m_state->EventChangedFlag = true;
        break;
    case 'k':
    case 'K':
        m_state->C_event = States::S_Size;
        m_state->EventChangedFlag = true;
        break;
    case 'n':
    case 'N':
        m_state->C_event = States::N_Object;
        m_state->EventChangedFlag = true;
        break;
    case 'r':
    case 'R':
        m_state->C_event = States::R_Size;
        m_state->EventChangedFlag = true;
        break;
    case 'p':
    case 'P':
    case ' ':
        m_state->Pause();
        break;
    case 'f':
    case 'F':
        m_state->PreFrame();
        break;
    case 'e':
    case 'E':
        m_state->C_event = States::N_Size;
        m_state->EventChangedFlag = true;
        break;
    default:
        break;
    }
    m_state->OnKey(m_state->C_event);
}

void ShellGUIImpl::onMouse( int event, int x, int y, int, void* )
{
    States *state = ShellGUIImpl::_guiimpl->m_state;
    States::Mouse_Event m_event;

    switch(event)
    {
    case CV_EVENT_LBUTTONDOWN:
        m_event = States::L_Button_Down;
        break;
    case CV_EVENT_LBUTTONUP:
        m_event = States::L_Button_Up;
        break;
    case CV_EVENT_RBUTTONDOWN:
        m_event = States::R_Button_Down;
        break;
    case CV_EVENT_RBUTTONUP:
        m_event = States::R_Button_Up;
        break;
    default:
        m_event = States::N_Button;
    }
    state->OnMouse(m_event, x, y);
}
